home *** CD-ROM | disk | FTP | other *** search
- TITLE COMPARE.ASM
- PAGE 60,132
-
- ;-------------------------------------------;
- ; COMPARE - Compares text and binary files ;
- ; PC Magazine - Michael J. Mefford ;
- ;-------------------------------------------;
-
- _TEXT SEGMENT PUBLIC 'CODE' ;********************************;
- ASSUME CS:_TEXT,DS:_TEXT ;* *;
- ASSUME ES:_TEXT,SS:_TEXT ;* Requires MASM 2.0 or later *;
- ;* Remember to EXE2BIN *;
- ORG 100H ;* *;
- START: JMP MAIN ;********************************;
-
-
- ; DATA AREA
- ; ---------
- SYNTAX_MSG DB CR,SPACE,SPACE,SPACE,CR,LF
-
- COPYRIGHT DB "COMPARE 1.0 (C) 1988 Ziff Communications Co.",CR,LF
- PROGRAMMER DB "PC Magazine ",BOX," Michael J. Mefford",CR,LF,CR,LF
-
- DB "Syntax: COMPARE filespec filespec[/B][/W]",CR,LF
- DB "/B = Binary /W = WordStar$",CTRL_Z
-
- TAB EQU 9
- CR EQU 13
- LF EQU 10
- CTRL_Z EQU 26
- SPACE EQU 32
- BOX EQU 254
-
- CRT_MODE EQU 49H
- CRT_COLS EQU 4AH
- ADDR_6845 EQU 63H
- TEN_K EQU 10 * 1024
- _64K_PARA EQU 64 * (1024 / 16)
- SPEC_LENGTH EQU 80
-
- LINE_CHAR EQU 0CDH
- LF_BAR_CHAR EQU 0B5H
- RT_BAR_CHAR EQU 0C6H
- BLINKING EQU 10000000B
-
- STATUS_REG DW ?
- VIDEO_SEG DW 0B000H
- COLS DW ?
- ROWS DB 24
- NORMAL_ATTRIB DB 07H
- INVERSE_ATTRIB DB 70H
- STRIP_MASK DB 0FFH
- SYNTAX_FLAG DB 0
- DISPLAY_FLAG DB 1
- MISMATCH_FLAG DB 0
- WINDOW_FULL DB 0
-
- FILE_START DW FILE1_BUFFER2, FILE2_BUFFER2 ;CONSTANT
- FILE_POS DW 2 DUP (?)
- FILE_END DW 2 DUP (?)
- BUFFER_END DW FILE1_BUFFER2 + TEN_K, FILE2_BUFFER2 + TEN_K
- WINDOW_POS DW 2 DUP (?)
- WINDOW_COL DW 2 DUP (?)
- WINDOW_LINE DW 2 DUP (?)
- WINDOW_SIZE DB ?
-
- SAVE_COL DW 80,80
- SAVE_POS DW FILE1_BUFFER2, FILE2_BUFFER2
- SYNC_POS DW 2 DUP (?)
- LINE_ARRAY DW 2 DUP (4 DUP (?))
- LINE_CAPACITY DW ?
- STATUS_LINE DW ?
- HEX_SEGMENT DW 2 DUP (0)
- HEX_OFFSET DW 2 DUP (0)
-
- FILENAME DW FILESPEC + 2, FILESPEC + SPEC_LENGTH + 2
- FILE_HANDLE DW 2 DUP (?)
-
- NOT_ENOUGH DB "Requires 64K free RAM$"
- BAD_MODE_MSG DB "Unsupported video mode$"
- BINARY_NAME DB "COMEXE"
- PROMPT DW PROMPT1, PROMPT2
- PROMPT1 DB CR,LF,LF,"Enter first file name",CR,LF,"$"
- PROMPT2 DB CR,LF,LF,"Enter second file name",CR,LF,"$"
- NOT_FOUND_MSG DB CR,LF,"File not found$"
-
- MENU DB "Press any key for next compare Esc to Exit",0
- MENU_LENGTH EQU $ - MENU - 1
- WORKING_MSG DB "Working",0
- WORKING_LENGTH EQU $ - WORKING_MSG - 1
- DIFF_MSG DB "Files significantly different",0
- DIFF_LENGTH EQU $ - DIFF_MSG - 1
- SAME_MSG DB "Files are effectively identical",0
- SAME_LENGTH EQU $ - SAME_MSG - 1
- DONE_MSG DB "Compare completed",0
- DONE_LENGTH EQU $ - DONE_MSG - 1
-
-
- ; CODE AREA
- ; ---------
- MAIN PROC NEAR
-
- CLD ;String instructions forward.
-
- MOV BX,_64K_PARA ;Make sure we have 64K to
- MOV AH,4AH ; to work in.
- INT 21H
- MOV DX,OFFSET NOT_ENOUGH ;Exit if cramped, else continue.
- JNC CK_SWITCH
- JMP ERROR_EXIT
-
- ;--------------------------------------------------------;
- ; Check for /B Binary and /W WordStar switch characters. ;
- ;--------------------------------------------------------;
-
- CK_SWITCH: MOV SI,81H ;Point to command line.
- NEXT_SWITCH: LODSB ;Get a byte.
- CMP AL,CR ;Is it carriage return?
- JZ PARSE ;If yes, done here.
- CMP AL,"/" ;Is it switch delimiter?
- JNZ NEXT_SWITCH ;If no, next byte.
- MOV BYTE PTR [SI-1],0 ;Else, ASCIIZ it out.
- LODSB ;Get the switch character.
- CMP AL,CR ;Make sure it's not CR
- JZ PARSE ; so we don't go past end.
- MOV BYTE PTR [SI-1],0 ;ASCIIZ switch character also.
- AND AL,5FH ;Capitalize.
- CMP AL,"W"
- JNZ CK_BINARY ;If it's not "W", then skip.
- MOV STRIP_MASK,7FH ;Else, we will strip high bit.
-
- CK_BINARY: CMP AL,"B" ;Is it "B"?
- JNZ NEXT_SWITCH ;If no, next byte.
- MOV LINE_CAPACITY,16 ;Else, do hex compare.
- JMP SHORT NEXT_SWITCH ;Next byte.
-
- ;---------------------------------------------------------------;
- ; Parse the command line for filespecs. If one or both missing ;
- ; or file can't be opened, prompt the user for filespec. ;
- ;---------------------------------------------------------------;
-
- PARSE: MOV SI,81H ;Point to command line again.
- XOR BP,BP ;Initialize filespec counter.
- NEXT_PARSE: LODSB ;Get a byte.
- CMP AL,SPACE ;Parse off leading delimiters
- JA LEADING_END
- CMP AL,CR ; as long as it's not ending
- JNZ NEXT_PARSE ; carriage return.
- LEADING_END: DEC SI ;Adjust pointer.
- MOV DI,SI ;Save as filespec start position.
- MOV DX,SI
-
- FIND_END: LODSB ;Get a byte.
- CMP AL,SPACE ;Are we at end of filespec?
- JA FIND_END
- MOV BYTE PTR [SI-1],0 ;If yes, make ASCIIZ.
- PUSH SI ;Save our place.
- PUSH AX ;And save the character.
- CALL OPEN_FILE ;Try to open the file.
- JNC RESTORE_PARSE ;If successful, get next filespec
- CALL PROMPT_USER ; else, prompt user for filespec.
-
- RESTORE_PARSE: POP AX ;Restore last parsed character
- POP SI ; and position.
- STORE_START: MOV FILENAME[BP],DI ;Store pointer to filename.
- ADD BP,2 ;Next filespec.
- CMP BP,2
- JA CAP
- CMP AL,CR ;Was last character parsed CR?
- JNZ NEXT_PARSE ;If no, get next.
- CALL PROMPT_USER ;Else prompt user for filespec
- JMP SHORT STORE_START ; and store pointer to it.
-
- ;----------------------------------------------------------------------------;
- ; Capitalize filenames so parameter parsing can be done with one compare. ;
- ;----------------------------------------------------------------------------;
-
- CAP: MOV BP,2 ;Two filenames to capitalize.
- CAPITALIZE: MOV SI,FILENAME[BP] ;Point to filename.
- NEXT_CAP: LODSB ;Get a byte.
- CMP AL,0 ;Is it ASCIIZ?
- JZ LOOP_CAP ;If yes, next name.
- CMP AL,"a" ;Is it a lower case a - z?
- JB NEXT_CAP
- CMP AL,"z"
- JA NEXT_CAP
- AND BYTE PTR [SI-1],5FH ;If yes, capitalize.
- JMP SHORT NEXT_CAP
-
- LOOP_CAP: SUB BP,2 ;Capitalize both names.
- JNC CAPITALIZE
-
- ;-----------------------------------------------------------------------------;
- ; Automatically do a binary compare if filespec has a .COM or .EXE extension. ;
- ;-----------------------------------------------------------------------------;
-
- MOV BP,2
- BINARY: MOV SI,FILENAME[BP] ;Point to filename.
- NEXT_BINARY: LODSB ;Get a byte.
- CMP AL,0 ;Is it ASCIIZ?
- JZ LOOP_BINARY ;If yes, done here.
- CMP AL,"." ;Is it delimiting dot char?
- JNZ NEXT_BINARY ;If no, next byte.
- MOV BX,2 ;Two possible binary names --
- MOV DI,OFFSET BINARY_NAME ; .COM and .EXE.
-
- NEXT_EXEC: PUSH SI ;Save our place.
- PUSH DI
- MOV CX,3 ;Do we have a match?
- REP CMPSB
- POP DI ;Restore our place.
- POP SI
- JZ BINARY_FILE ;If match, mark a binary compare.
- ADD DI,3 ;Else point to next extension
- DEC BX
- JNZ NEXT_EXEC ; and check if it matches.
- JMP SHORT NEXT_BINARY
-
- LOOP_BINARY: SUB BP,2 ;Do both filenames.
- JNC BINARY
- JMP SHORT READY
-
- BINARY_FILE: MOV LINE_CAPACITY,16 ;Else, do hex compare.
-
- ;---------------------------------------------------------------------;
- ; Line array is used to keep track of the start of file line displays ;
- ; so we can display three lines preceeding mismatch for context. ;
- ;---------------------------------------------------------------------;
-
- READY: MOV AX,FILE_START[0] ;Initalize current line-starts
- MOV LINE_ARRAY[6],AX ; of array to start of file.
- MOV AX,FILE_START[2]
- MOV LINE_ARRAY[14],AX
-
- CALL VIDEO_SETUP ;Prepare for video environment.
- CALL DISPLAY_SETUP ;Initialize display with heading
- ; and window delimiting lines.
-
- ;---------------------------------------------------------------------------;
- ; We will loop here filling the window with mismatches until all displayed. ;
- ;---------------------------------------------------------------------------;
-
- DO_SEARCH: CALL SEARCH ;Search for mismatches.
- JNC GET_KEY ;If not carry, not done yet.
- CALL CLS_MENU ;If done, clear menu.
- MOV DI,STATUS_LINE
- ADD DI,COLS
- MOV BH,NORMAL_ATTRIB
- CMP MISMATCH_FLAG,1 ;Display appropriate message
- JZ DO_DONE_MSG
- MOV SI,OFFSET SAME_MSG
- SUB DI,SAME_LENGTH AND NOT 1
- JMP SHORT MESSAGE_EXIT
- DO_DONE_MSG: MOV SI,OFFSET DONE_MSG
- SUB DI,DONE_LENGTH AND NOT 1
- JMP SHORT MESSAGE_EXIT
-
- GET_KEY: CALL DISPLAY_MENU ;If not done, display menu.
- CALL CLEAR_KEY ;Clear any awaiting keystroke.
- CALL READ_KEY ;Get a keystroke.
- CMP AH,1 ;Is it Esc?
- JNZ DO_SEARCH ;If no, search for next mismatch.
- CALL CLS_MENU ;Else, clear menu
- JMP SHORT GOOD_EXIT ; and exit.
-
- ;--------------------------------------------------------------;
- ; Exit with appropriate message and put cursor back on screen. ;
- ;--------------------------------------------------------------;
-
- ERROR_EXIT: CALL PRINT_STRING ;Print error message.
- MOV AL,1 ;Exit with error level one.
- JMP SHORT EXIT
-
- MESSAGE_EXIT: CALL WRITE_STRING ;Display exit message.
- GOOD_EXIT: MOV DH,ROWS ;Move cursor to next to last
- DEC DH ; line of screen.
- XOR DL,DL
- XOR BH,BH
- MOV AH,2
- INT 10H
- XOR AL,AL ;Error level zero.
- EXIT: MOV AH,4CH ;Terminate.
- INT 21H
-
- MAIN ENDP
-
- ; ***************
- ; * SUBROUTINES *
- ; ***************
-
- ;-------------------------------------;
- ; INPUT ;
- ; None ;
- ; ;
- ; OUTPUT ;
- ; Carry flag = 1 if search complete ;
- ; Carry flag = 0 if more to search. ;
- ; ;
- ; All registers destroyed. ;
- ;-------------------------------------;
-
- SEARCH PROC NEAR
-
- ;--------------------------------------------------------;
- ; Display "Working" message and initialization variables ;
- ;--------------------------------------------------------;
-
- CALL CLS_MENU ;Clear the menu.
- MOV SI,OFFSET WORKING_MSG ;Display "Working"
- MOV DI,STATUS_LINE
- ADD DI,80 - WORKING_LENGTH AND NOT 1
- MOV BH,NORMAL_ATTRIB
- OR BH,BLINKING ; with blinking attribute.
- CALL WRITE_STRING
-
- MOV AX,COLS
- SHL AX,1 ;Double for attribute.
- MOV DI,AX
- SHL DI,1 ;Second line.
- MOV WINDOW_POS[0],DI ;Initialize window pointers
- MOV DL,WINDOW_SIZE
- INC DL
- MUL DL ; to top left corner of
- ADD DI,AX ; each window.
- MOV WINDOW_POS[2],DI
-
- MOV BP,2 ;Restore the window columns,
- RESTORE_WIN: MOV AX,SAVE_COL[BP] ; window lines and file
- MOV WINDOW_COL[BP],AX ; positions to what they were
- MOV AX,SAVE_POS[BP] ; when one of the windows
- MOV FILE_POS[BP],AX ; was filled last search.
- MOV AL,WINDOW_SIZE
- XOR AH,AH
- MOV WINDOW_LINE[BP],AX
- SUB BP,2
- JNC RESTORE_WIN
-
- MOV DI,OFFSET LINE_ARRAY ;Initialize the array of
- MOV AX,LINE_ARRAY[6] ; line starts to the last
- MOV CX,4 ; line start from previous
- REP STOSW ; search.
- MOV AX,LINE_ARRAY[14]
- MOV CX,4
- REP STOSW
-
- MOV WINDOW_FULL,0 ;Flag that windows are not full.
- MOV DISPLAY_FLAG,0 ;No display during search.
-
- ;------------------------------------------------------------------------------;
- ; Check to see if End of File has been reached and/or windows have been filled ;
- ;------------------------------------------------------------------------------;
-
- NEXT_SEARCH: MOV SI,FILE_POS[0] ;Get current file position.
- MOV DI,FILE_POS[2]
- CALL STORE_WINDOW ;See if current postion to be
- CALL CK_EOF1 ; frozen for next search.
- JNC CK_WINDOW2 ;If both End of Files reached
- CALL CK_EOF2 ; then compare complete.
- JNC CK_WIN_FULL
- STC
- RET
-
- CK_WINDOW2: CALL CK_EOF2 ;If neither EOF then continue.
- JNC BOTH_WINDOWS
- CK_WIN_FULL: TEST WINDOW_FULL,111B ;If one EOF and windows full
- JZ COMPARE ; then return, else continue.
- JMP SHORT SEARCH_END
-
- BOTH_WINDOWS: CMP WINDOW_FULL,111B ;If both windows full, return.
- JZ SEARCH_END
-
- ;------------------------------------------------------------------------;
- ; Files are compared a byte at a time until mismatch is found. ;
- ; In comparing text files, if one byte is a carriage return and it is ;
- ; mismatch with a space then both are ignored (line wrap); else just ;
- ; the CR is ignored (word wrap). No special treatment for binary files. ;
- ;------------------------------------------------------------------------;
-
- COMPARE: MOV BH,NORMAL_ATTRIB ;Use normal attribute.
- CALL CK_EOF1 ;If either EOF then match
- JC DO_MISMATCH ; not possible.
- CALL CK_EOF2
- JC DO_MISMATCH
- MOV AL,[SI] ;Get a byte from each file.
- MOV AH,[DI]
- CMPSB ;Are they the same?
- JZ FORMAT_BOTH ;If yes, format display.
- CMP LINE_CAPACITY,16 ;If no, is it a binary compare?
- JZ DO_MISMATCH ;If yes, mismatch.
- CMP AL,LF ;Else, is it linefeed?
- JZ ADJUST_2A ;If yes, ignore.
- CMP AL,CR ;If CR, check if matched
- JZ CK_ADJUST_2A ; with a space character.
- CMP AH,LF ;Do the same for both files.
- JZ FORMAT_1A
- CMP AH,CR
- JNZ DO_MISMATCH
-
- CK_ADJUST_1A: CMP AL,SPACE ;If CR matched with space,
- JZ FORMAT_BOTH ; format both characters.
- ADJUST_1A: JMP SHORT FORMAT_1A ;Else, just format the CR.
-
- CK_ADJUST_2A: CMP AH,SPACE ;Do the same for other file.
- JZ FORMAT_BOTH
- ADJUST_2A: XOR BP,BP ;File one index.
- JMP SHORT FORMAT_2A
-
- FORMAT_BOTH: XOR BP,BP
- CALL FORMAT
- FORMAT_1A: MOV BP,2 ;File two index.
- MOV AL,AH ;Call format with character
- FORMAT_2A: CALL FORMAT ; in AL.
- JMP NEXT_SEARCH ;Check next bytes.
-
- DO_MISMATCH: MOV MISMATCH_FLAG,1 ;Flag that mismatch found.
- CALL MISMATCH ;Go highlight the mismatch.
- JMP NEXT_SEARCH ;Check next bytes.
-
- SEARCH_END: CLC
- RET
-
- SEARCH ENDP
-
- ;------------------------------------;
- ; INPUT ;
- ; AL = Character to format. ;
- ; BP = Index to file. ;
- ; ;
- ; OUTPUT ;
- ; WINDOW_COL[BP] WINDOW_LINE[BP] ;
- ; WINDOW_FULL FILE_POS[BP] ;
- ; are updated. ;
- ; ;
- ; AX, BX, CX, SI and DI preserved. ;
- ;------------------------------------;
-
- FORMAT PROC NEAR
-
- PUSH AX ;Preserve registers.
- PUSH CX
- PUSH SI
- PUSH DI
- MOV CX,WINDOW_COL[BP] ;Retrieve current column.
- CMP LINE_CAPACITY,16 ;Are we working on a binary file?
- JZ DO_HEX ;If yes, do a hex display.
- CALL LINES ;Else, display text lines.
- JMP SHORT CK_LINE_START
-
- DO_HEX: CALL HEX
-
- CK_LINE_START: INC FILE_POS[BP] ;Increment file position.
- JCXZ LINE_START ;End of a display line?
- MOV WINDOW_COL[BP],CX ;If no, store column postion
- JMP SHORT FORMAT_END ; and return.
-
- LINE_START: MOV AX,LINE_CAPACITY ;Else, go to next column.
- MOV WINDOW_COL[BP],AX
- CMP AX,16 ;Are we doing a binary compare?
- JZ CK_ARRAY ;If yes, skip CR check.
- OR BP,BP ;Else, check if EOF.
- JNZ CK_CR2
- CALL CK_EOF1
- JMP SHORT CK_CR
- CK_CR2: CALL CK_EOF2
- CK_CR: JC CK_ARRAY ;If EOF, skip CR check.
- MOV DI,FILE_POS[BP] ;Else, if byte at end of an 80
- CMP BYTE PTR [DI],CR ; column display is CR, bump
- JNZ CK_ARRAY ; file postion past it so
- INC FILE_POS[BP] ; don't double space display.
-
- CK_ARRAY: CMP DISPLAY_FLAG,1 ;Are we displaying?
- JNZ ADJUST_ARRAY ;If no, skip line check.
- CMP WINDOW_LINE[BP],0 ;Else, is window full?
- JZ FORMAT_END ;If yes, done here.
- DEC WINDOW_LINE[BP] ;Else, decrement line display.
- JNZ ADJUST_ARRAY ;If window not full, skip next.
- MOV CX,BP ;Else, mark appropriate
- ADD CL,2 ; WINDOW_FULL bit as full.
- OR WINDOW_FULL,CL
- JMP SHORT FORMAT_END
-
- ADJUST_ARRAY: TEST WINDOW_FULL,001B ;Has window been stored?
- JNZ FORMAT_END ;If yes, skip array indexing.
- CALL ARRAY_INDEX ;Else, index into array.
- MOV SI,DI
- ADD SI,2
- MOV CX,3
- REP MOVSW ;Move all line starts up one
- MOV AX,FILE_POS[BP]
- MOV [DI],AX ; and store new line start.
- FORMAT_END: POP DI ;Restore registers.
- POP SI
- POP CX
- POP AX
- RET
-
- FORMAT ENDP
-
- ;------------------------------;
- ; INPUT ;
- ; AL = Character to display. ;
- ; CX = current column. ;
- ; BP = Index to file. ;
- ; ;
- ; OUTPUT ;
- ; CX = new column. ;
- ; WINDOW_POS[BP] is updated. ;
- ; ;
- ; BX preserved. ;
- ;------------------------------;
-
- LINES PROC NEAR
-
- CMP AL,CR ;Carriage return?
- JZ PAD_SPACES ;If yes, pad balance of line.
- CMP AL,TAB ;Is it tab character?
- JZ EXPAND_TAB ;If yes, expand to spaces.
- CMP AL,LF ;Is it linefeed?
- JZ LINES_END ;If yes, skip.
-
- PUSH CX ;Save column.
- MOV CX,1 ;Display one character.
- CALL CK_DISPLAY
- POP CX ;Restore column and decrement.
- DEC CX
- RET
-
- EXPAND_TAB: PUSH CX ;Save column.
- DEC CX ;Adjust column counter.
- AND CX,7 ;Get bottom three bits.
- INC CX ;Adjust.
- PUSH CX ;Save.
- CALL PAD_SPACES ;Move to next tab position.
- POP AX
- POP CX
- SUB CX,AX ;Adjust column counter.
- RET
-
- PAD_SPACES: MOV AL,SPACE ;If CR display spaces.
- CK_DISPLAY: CMP DISPLAY_FLAG,1 ;Are we to write it to screen?
- JNZ DISPLAY_END ;If no, return.
- CMP WINDOW_LINE[BP],0 ;Window full?
- JZ DISPLAY_END ;If yes, return.
- MOV DI,WINDOW_POS[BP] ;Else, retrieve display position.
- WRITE_VIEW: CALL WRITE_SCREEN ;Write character CX times.
- LOOP WRITE_VIEW
- MOV WINDOW_POS[BP],DI ;Store new display position.
-
- DISPLAY_END: XOR CX,CX
- LINES_END: RET
-
- LINES ENDP
-
- ;------------------------------;
- ; INPUT ;
- ; AL = Character to display. ;
- ; CX = current column. ;
- ; BP = Index to file. ;
- ; ;
- ; OUTPUT ;
- ; CX = new column. ;
- ; WINDOW_POS[BP] is updated. ;
- ; ;
- ; BX preserved. ;
- ;------------------------------;
-
- HEX PROC NEAR
-
- CMP DISPLAY_FLAG,1 ;Are we to write to screen?
- JNZ DEC_COLUMN ;If no, just update column.
- CMP WINDOW_LINE[BP],0 ;Else, is window full?
- JNZ GO_HEX ;If yes, continue.
- DEC_COLUMN: DEC CX ;Else, update column and return.
- RET
-
- GO_HEX: PUSH CX ;Save some registers.
- PUSH AX
- PUSH CX
-
- MOV DI,WINDOW_POS[BP] ;Retrieve window position.
- CMP CX,16 ;Is it first column?
- JNZ DISP_NUMBERS ;If no, just display the byte.
- PUSH AX ;Else, save character and
- PUSH BX ; attribute.
-
- MOV AX,FILE_POS[BP] ;Retrieve file position
- SUB AX,FILE_START[BP] ;Subtract the starting position.
- ADD AX,HEX_OFFSET[BP] ;Add the 64K offset.
- PUSH AX ;Save the offset.
- MOV AX,HEX_SEGMENT[BP] ;Retrieve segment.
- JNC DISP_SEGMENT ;Did offset carry?
- ADD AX,1000H ;If yes, add 1000h to segment.
-
- DISP_SEGMENT: MOV BH,NORMAL_ATTRIB ;Yes normal attribute.
- MOV CX,1 ;Segment and offset counter.
- NEXT_ADDRESS: XCHG AH,AL ;AL = byte to display.
- CALL DISPLAY_HEX
- XCHG AH,AL ;Get second byte to display.
- CALL DISPLAY_HEX
- OR CX,CX ;Segment and offset displayed?
- JZ ADDRESS_END ;If yes, done here.
- MOV AL,":" ;Else, display delimiting colon.
- CALL WRITE_SCREEN
- POP AX ;Retrieve offset.
- DEC CX ;Decrement counter.
- JMP SHORT NEXT_ADDRESS ;Display segment.
-
- ADDRESS_END: ADD DI,4 ;Move right two spaces.
- POP BX ;Retrieve attribute.
- POP AX ;Retrieve character.
-
- DISP_NUMBERS: CALL DISPLAY_HEX ;Display the hex number.
- MOV AL,SPACE ;Delimit with a space.
- POP CX ;Retrieve column counter.
- CMP CX,9 ;Is it half way?
- JNZ DELIMITER
- MOV AL,"-" ;If yes, display delimiting dash
- DELIMITER: PUSH BX ; with normal attribute.
- MOV BH,NORMAL_ATTRIB
- CALL WRITE_SCREEN
- POP BX ;Restore attribute.
- MOV WINDOW_POS[BP],DI ;Store window position.
- SHL CX,1 ;Multiply column by 8.
- SHL CX,1
- ADD DI,CX ;Add to current window postion.
- ADD DI,30 ;Tab over additional 15.
- POP AX ;Retrieve character and display.
- CALL WRITE_SCREEN
- POP CX ;Restore column counter
- DEC CX ; and update.
- JNZ HEX_END ;If last column, bump window
- MOV AX,COLS ; to next line.
- SUB AX,59
- SHL AX,1
- ADD WINDOW_POS[BP],AX
- HEX_END: RET
-
- HEX ENDP
-
- ;-------------------------------;
- ; INPUT ;
- ; AL = Hex number to display. ;
- ; ;
- ; OUTPUT ;
- ; none ;
- ; ;
- ; BX and CX preserved. ;
- ;-------------------------------;
-
- DISPLAY_HEX PROC NEAR
-
- PUSH CX ;Preserve CX.
- MOV CX,0204H ;2 char/byte; 4 bits/byte.
- ROTATE_HEX: ROL AL,CL ;Get next four bits.
- PUSH AX ;Save number.
- AND AL,00001111B ;Mask off high bits.
- ADD AL,30H ;Convert to ASCII.
- CMP AL,"9" ;Is it above 9?
- JLE PRINT_HEX
- ADD AL,7 ;If yes, convert to hex alpha.
- PRINT_HEX: CALL WRITE_SCREEN
- POP AX ;Restore number.
- DEC CH ;Do both hex characters.
- JNZ ROTATE_HEX
- POP CX
- RET
-
- DISPLAY_HEX ENDP
-
- ;----------------------------;
- ; INPUT ;
- ; BH = Display attribute. ;
- ; ;
- ; OUTPUT ;
- ; None ;
- ; ;
- ; All registers destroyed. ;
- ;----------------------------;
-
- MISMATCH PROC NEAR
-
- CMP DISPLAY_FLAG,1 ;Is this first time here?
- JZ SYNCHRONIZE ;If yes no context to display.
- MOV DISPLAY_FLAG,1 ;Else, flag to display.
- CALL CLS_WINDOWS ;Clear the windows.
-
- MOV BP,2 ;Two windows.
- NEXT_WINDOW: MOV AX,LINE_CAPACITY ;Restore line to first column.
- MOV WINDOW_COL[BP],AX
- MOV CX,FILE_POS[BP] ;Save current position.
- CALL ARRAY_INDEX
- MOV AX,[DI] ;Retrieve third line back.
- MOV FILE_POS[BP],AX
- NEXT_CONTEXT: MOV SI,FILE_POS[BP] ;Display context until current
- CMP SI,CX ; mismatch position.
- JAE LOOP_WINDOW
- LODSB
- CALL FORMAT
- JMP SHORT NEXT_CONTEXT
-
- LOOP_WINDOW: SUB BP,2 ;Do both windows.
- JNC NEXT_WINDOW
-
- ;-----------------------------------------------------------------------------;
- ; Try to synchronize by matching 10 bytes up to 200 postions away from ;
- ; current position. In text files, ignore spaces so won't get false matches. ;
- ;-----------------------------------------------------------------------------;
-
- SYNCHRONIZE: MOV BX,FILE_POS[0] ;File 1 postion in BX.
- MOV CX,400 ;400 byte reach.
-
- NEXT_SYNC: PUSH CX ;Save counter.
- MOV DX,FILE_POS[2] ;Second file position in DX.
- MOV CX,400 ;Also a 400 byte reach.
-
- NEXT_TRY: PUSH CX ;Save counter.
- MOV CX,10 ;Require 10 bytes for match.
-
- MOV SI,BX ;Initialize pointers.
- MOV DI,DX
- NEXT_CHAR: CALL CK_EOF1 ;EOF of file one?
- JC NEXT_TRY_END ;If yes, increment file 2.
- CALL CK_EOF2 ;EOF of file two?
- JC FILE2_END ;If yes, increment file 1.
- MOV AL,[SI] ;Retrieve characters.
- MOV AH,[DI]
- CMPSB ;Do they match?
- JZ POSSIBLE_SYNC ;If yes, poss. synchronization.
- CMP LINE_CAPACITY,16 ;Else, is it binary compare?
- JZ NEXT_TRY_END ;If yes, no match.
- CMP AL,LF ;Else, if linefeed, ignore.
- JZ ADJUST_2B
- CMP AL,CR ;If carriage return, ignore
- JZ CK_ADJUST_2B ; and ignore any match space.
- CMP AH,LF ;Do same check for both files.
- JZ ADJUST_1B
- CMP AH,CR
- JNZ NEXT_TRY_END
-
- CK_ADJUST_1B: CMP AL,SPACE ;If CR with space, ignore both.
- JZ NEXT_CHAR
- ADJUST_1B: DEC SI ;Else, ignore CR only.
- JMP SHORT NEXT_CHAR
-
- CK_ADJUST_2B: CMP AH,SPACE ;Do same for both files.
- JZ NEXT_CHAR
- ADJUST_2B: DEC DI
- JMP SHORT NEXT_CHAR
-
- POSSIBLE_SYNC: CMP AL,SPACE ;If sync char is space, ignore.
- JZ NEXT_CHAR
- LOOP NEXT_CHAR ;Need ten matches for sync.
- JMP SHORT EVALUATE
-
- FILE2_END: POP CX ;If file 2 EOF, skip to
- JMP SHORT NEXT_SYNC_END ; next file 1 postion.
-
- NEXT_TRY_END: INC DX ;Increment file 2 postion.
- POP CX ;Decrement reach counter.
- LOOP NEXT_TRY ;Keep trying up to 400 positions.
-
- NEXT_SYNC_END: INC BX ;Increment file 1 position.
- POP CX ;Decrement reach counter.
- LOOP NEXT_SYNC ;Keep trying up to 400 positions.
-
- PUSH SI ;Save pointers.
- PUSH DI
- MOV SI,OFFSET DIFF_MSG
- MOV DI,STATUS_LINE
- MOV AX,COLS
- SHL AX,1
- SUB AX,DIFF_LENGTH * 2
- ADD DI,AX
- PUSH BX
- PUSH DX ;Display "Files significantly
- MOV BH,NORMAL_ATTRIB ; different" if didn't find
- CALL WRITE_STRING ; a match.
- POP DX
- POP BX
- POP DI
- POP SI
- JMP SHORT EVALUATE_EOF
-
- ;--------------------------------------------;
- ; Display mismatch until EOF or window full. ;
- ;--------------------------------------------;
-
- EVALUATE: POP CX ;Fix stack.
- POP CX
- EVALUATE_EOF: CALL CK_EOF1 ;EOF of file 1?
- JNC EOF2
- MOV BX,FILE_END[0] ;If yes, use file end pointer.
- EOF2: CALL CK_EOF2 ;EOF of file 2?
- JNC INVERSE
- MOV DX,FILE_END[2] ;If yes, use file end pointer.
- INVERSE: MOV SYNC_POS[0],BX ;Save synchronization position.
- MOV SYNC_POS[2],DX
- MOV BH,INVERSE_ATTRIB ;Display in inverse attribute.
-
- MOV BP,2 ;Two windows to display.
- HIGHLIGHT: MOV SI,FILE_POS[BP] ;Is current postion = sync pos?
- CMP SI,SYNC_POS[BP]
- JZ LOOP_INVERSE ;If yes, done.
- CMP WINDOW_LINE[BP],0 ;Is window full?
- JZ LOOP_INVERSE ;If yes, done.
- LODSB ;Else, display mismatch.
- CALL FORMAT
- JMP SHORT HIGHLIGHT
-
- LOOP_INVERSE: SUB BP,2 ;Do both windows.
- JNC HIGHLIGHT
- EVALUATE_END: CALL STORE_WINDOW ;Freeze postion if window full.
- MOV BP,2 ;Restore current position.
- RESTORE_POS: MOV AX,SYNC_POS[BP]
- MOV FILE_POS[BP],AX
- SUB BP,2
- JNC RESTORE_POS
- RET
-
- MISMATCH ENDP
-
- ;----------------------------;
- ; INPUT ;
- ; None ;
- ; ;
- ; OUTPUT ;
- ; None ;
- ; ;
- ; AX and BP destroyed. ;
- ;----------------------------;
-
- STORE_WINDOW PROC NEAR
-
- ;------------------------------------------------------------------------;
- ; As soon as a window becomes full, freeze the position for next search. ;
- ;------------------------------------------------------------------------;
-
- TEST WINDOW_FULL,110B ;Either window full?
- JZ STORE_END ;If no, done.
- TEST WINDOW_FULL,001B ;Else, have we already stored?
- JNZ STORE_END ;If yes, done.
- OR WINDOW_FULL,001B ;Else, flag stored.
- MOV BP,2
- FREEZE_POS: MOV AX,FILE_POS[BP] ;And store current position
- MOV SAVE_POS[BP],AX
- MOV AX,WINDOW_COL[BP] ; and column.
- MOV SAVE_COL[BP],AX
- SUB BP,2
- JNC FREEZE_POS
- STORE_END: RET
-
- STORE_WINDOW ENDP
-
- ;---------------------------------;
- ; INPUT ;
- ; SI and DI = current position. ;
- ; Two entry points: ;
- ; CK_EOF1 and CK_EOF2 ;
- ; ;
- ; OUTPUT ;
- ; Carry flag = 1 if EOF. ;
- ; Carry flag = 0 if not EOF. ;
- ; ;
- ; BP destroyed. ;
- ;---------------------------------;
-
- CK_EOF PROC NEAR
-
- ;-----------------------------------------------------------------;
- ; These two subroutines read the next 10K bytes if end of buffer ;
- ; reached and EOF not reached. The second buffer is moved to the ;
- ; first buffer and all appropriate pointers are adjusted. ;
- ;-----------------------------------------------------------------;
-
- CK_EOF1: XOR BP,BP ;File index pointer.
- CMP SI,FILE_END[BP] ;Is position = EOF?
- JB NOT_EOF ;If no, not EOF.
- CMP SI,BUFFER_END[BP] ;Else, is it at end of buffer?
- JB EOF ;If no, EOF.
- JMP SHORT MOVE_BUFFER ;Else, more to file; read it.
-
- CK_EOF2: MOV BP,2 ;Do same for file 2.
- CMP DI,FILE_END[BP]
- JB NOT_EOF
- CMP DI,BUFFER_END[BP]
- JB EOF
-
- MOVE_BUFFER: PUSH AX ;Save registers.
- PUSH BX
- PUSH CX
- PUSH DX
- PUSH SI
- PUSH DI
- MOV SI,FILE_START[BP] ;Retrieve buffer start address.
- MOV DI,SI
- SUB DI,TEN_K
- MOV CX,TEN_K / 2 ;And move data to buffer
- REP MOVSW ; 10K below.
-
- CALL READ_FILE ;Read the next 10K.
- SUB SAVE_POS[BP],TEN_K ;Adjust all the pointers by 10K.
- SUB SYNC_POS[BP],TEN_K
- SUB FILE_POS[BP],TEN_K
- ADD HEX_OFFSET[BP],TEN_K ;Add 10K to offset.
- JNC DO_ARRAY ;If carry, add 1000h to segment.
- ADD HEX_SEGMENT[BP],1000H
- DO_ARRAY: CALL ARRAY_INDEX ;Adjust line start array.
- MOV CX,4
- SUB_ARRAY: SUB [DI],TEN_K
- INC DI
- INC DI
- LOOP SUB_ARRAY
- POP DI
- POP SI
- POP DX
- POP CX
- POP BX
- POP AX
- OR BP,BP ;If file 1, adjust DI and DX.
- JZ ADJUST_FILE1
- SUB DI,TEN_K
- SUB DX,TEN_K
- JMP SHORT NOT_EOF
- ADJUST_FILE1: SUB SI,TEN_K ;Else, adjust SI and BX.
- SUB BX,TEN_K
-
- NOT_EOF: CLC
- RET
-
- EOF: STC
- RET
-
- CK_EOF ENDP
-
- ;-----------------------------------;
- ; INPUT ;
- ; BP = file index. ;
- ; ;
- ; OUTPUT ;
- ; DI = start of line-start array. ;
- ; ;
- ; All registers preserved. ;
- ;-----------------------------------;
-
- ARRAY_INDEX PROC NEAR
-
- MOV DI,BP
- SHL DI,1 ;Multiply file index by 4
- SHL DI,1 ; to index into index.
- ADD DI,OFFSET LINE_ARRAY
- RET
-
- ARRAY_INDEX ENDP
-
- ;-----------------------------------;
- ; INPUT ;
- ; BP = file index ;
- ; DX = points to ASCIIZ filename. ;
- ; ;
- ; OUTPUT ;
- ; Carry flag = 1 if failed. ;
- ; Carry flag = 0 if successful. ;
- ; ;
- ; BP preserved. ;
- ;-----------------------------------;
-
- OPEN_FILE PROC NEAR
-
- MOV AX,3D00H ;Open file for reading.
- INT 21H
- JC OPEN_END
- MOV FILE_HANDLE[BP],AX ;Save file handle if successful
- CALL READ_FILE ; and read 10K.
- OPEN_END: RET
-
- OPEN_FILE ENDP
-
- ;-----------------------------------;
- ; INPUT ;
- ; BP = file index ;
- ; DX = points to ASCIIZ filename. ;
- ; ;
- ; OUTPUT ;
- ; Carry flag = 1 if failed. ;
- ; Carry flag = 0 if successful. ;
- ; ;
- ; BP preserved. ;
- ;-----------------------------------;
-
- READ_FILE PROC NEAR
-
- MOV BX,FILE_HANDLE[BP] ;Retrieve filehandle.
- MOV DX,FILE_START[BP] ;Point to storage buffer.
- MOV SI,DX ;Save it.
- MOV CX,TEN_K ;Read maximum of 10K.
- MOV AH,3FH ;Read file.
- INT 21H
- JC READ_FILE_END ;If failed, exit.
- ADD DX,AX ;Else, add bytes read to buffer
- MOV FILE_END[BP],DX ; address and store as file end.
-
- MOV CX,AX ;Bytes read in counter.
- JCXZ READ_END ;Skip if zero bytes read.
- MOV AL,STRIP_MASK ;Else, retrieve strip mask.
- CMP AL,0FFH ;If not WordStar, skip.
- JZ READ_END
- WORDSTAR: AND DS:[SI],AL ;Else, strip the high bit
- INC SI ; of all bytes read.
- LOOP WORDSTAR
-
- READ_END: CLC
- READ_FILE_END: RET
-
- READ_FILE ENDP
-
- ;-----------------------------------;
- ; INPUT ;
- ; None ;
- ; ;
- ; OUTPUT ;
- ; None ;
- ; ;
- ; ES preserved. ;
- ;-----------------------------------;
-
- VIDEO_SETUP PROC NEAR
-
- PUSH ES ;Preserve ES.
- MOV AX,500H ;Make sure active page is zero.
- INT 10H
- MOV AX,40H ;Point to the ROM BIOS data area
- MOV ES,AX
-
- MOV AL,ES:CRT_MODE ;Retrieve current video mode.
- CMP AL,7 ;Is it mono mode?
- JZ SUPPORTED ;If yes, continue.
- CMP AL,3 ;Is it text?
- JBE SUPPORTED ;If yes, continue.
- UNSUPPORTED: MOV DX,OFFSET BAD_MODE_MSG ;Else, do not pass GO.
- JMP ERROR_EXIT ;Go directly to jail.
-
- SUPPORTED: MOV AH,12H
- MOV BL,10H
- INT 10H
- CMP BL,10H ;Is there an EGA?
- JZ CK_CGA ;If no, check if CGA.
-
- TEST ES:BYTE PTR [87H],8 ;Else, EGA_info; Is it active?
- JNZ CK_CGA ;If no, check CGA.
- XOR BH,BH ;Else, retrieve CRT rows.
- MOV AX,1130H
- PUSH ES
- INT 10H
- POP ES
- MOV ROWS,DL ;Save CRT rows.
-
- CK_CGA: MOV AL,ES:CRT_COLS ;Retrieve CRT cols.
- XOR AH,AH ;Zero in high half.
- MOV DX,AX ;Save it.
- MOV BX,LINE_CAPACITY ;Retrieve line capacity.
- CMP BX,16 ;Are we displaying hex?
- JNZ CAPACITY ;If no, store.
- MOV DX,BX ;Else, use 16 as capacity.
- CMP AL,40 ;Are we in 40 column mode?
- JZ UNSUPPORTED ;If yes, useless display.
-
- CAPACITY: MOV LINE_CAPACITY,DX ;Store capacity and initialize
- MOV SAVE_COL[0],DX ; columns.
- MOV SAVE_COL[2],DX
- MOV COLS,AX ;Store columns.
- SHL AX,1 ;Times two for attribute.
- MOV DL,ROWS ;Retrieve rows
- MUL DL ; and multiply.
- MOV STATUS_LINE,AX ;Save as address of status line.
- SUB DL,4 ;Subtract 4 from CRT rows
- SHR DL,1 ; and divide by two
- MOV WINDOW_SIZE,DL ; and save as window size.
-
- MOV AX,ES:ADDR_6845 ;Retrieve display card.
- ADD AX,6 ;Add six to get status register
- MOV STATUS_REG,AX ;Store as status register.
- CMP AX,3BAH ;Is it monochrome?
- JZ VIDEO_END ;If yes, done here.
- ADD VIDEO_SEG,800H ;Else, adjust video segment.
- MOV AH,8 ;Get attribute at cursor postion.
- INT 10H
- MOV NORMAL_ATTRIB,AH ;And save as forground.
- XOR AH,01110111B ;Flip color bits.
- MOV INVERSE_ATTRIB,AH ;And save as highlight attribute.
-
- VIDEO_END: POP ES ;Restore ES.
- RET
-
- VIDEO_SETUP ENDP
-
- ;-----------------------------------;
- ; INPUT ;
- ; AL = character to write. ;
- ; BH = attribute. ;
- ; ;
- ; OUTPUT ;
- ; None ;
- ; ;
- ; AL, BH, CX preserved. ;
- ;-----------------------------------;
-
- WRITE_SCREEN PROC NEAR
-
- PUSH ES
- MOV DX,VIDEO_SEG ;Point to screen segment.
- MOV ES,DX
- MOV DX,STATUS_REG ;Retrieve status register.
- MOV BL,AL ;Store character in BL.
-
- HORZ_RET: IN AL,DX ;Get status.
- RCR AL,1 ;Is it low?
- JC HORZ_RET ;If not, wait until it is.
- CLI ;No more interrupts.
-
- HWAIT: IN AL,DX ;Get status.
- RCR AL,1 ;Is it high?
- JNC HWAIT ;If no, wait until it is.
-
- MOV AX,BX ;Retrieve character; now it's OK
- STOSW ; to write to screen buffer.
- STI ;Interrupts back on.
- POP ES
- RET ;Return
-
- WRITE_SCREEN ENDP
-
- ;-----------------------------------;
- ; INPUT ;
- ; None ;
- ; ;
- ; OUTPUT ;
- ; None ;
- ; ;
- ; All registers destroyed. ;
- ;-----------------------------------;
-
- DISPLAY_SETUP PROC NEAR
-
- CALL CLS ;Clear screen.
- MOV DH,ROWS ;Retrieve CRT rows.
- INC DH ;Move one line below off screen.
- XOR DL,DL ;Column zero.
- XOR BH,BH ;Page zero.
- MOV AH,2 ;Set cursor position.
- INT 10H
-
- XOR DI,DI ;Point to top left of display.
- MOV SI,OFFSET COPYRIGHT ;Point to copyright message.
- MOV BH,NORMAL_ATTRIB ;And display it.
- CALL WRITE_STRING
- MOV DI,COLS ;Retrieve columns.
- SHL DI,1 ;Double for attribute.
- SUB DI,64 ;Right justify my name.
- INC SI ;Bump pointer past linefeed.
- CALL WRITE_STRING
-
- MOV BP,0 ;Initialize counter.
- NEXT_LINE: MOV CX,COLS ;Write line characters
- PUSH DI ;Save position.
- MOV AL,LINE_CHAR ; to screen.
- NEXT_WRITE: CALL WRITE_SCREEN
- LOOP NEXT_WRITE
-
- POP DI ;Retrieve position.
- CMP BP,2 ;Do two windows.
- JA SETUP_END
- PUSH DI ;Save screen pointer.
- ADD DI,10 ;Tab in five spaces
- MOV AL,LF_BAR_CHAR ; and print a left bar char.
- CALL WRITE_SCREEN
- MOV SI,FILENAME[BP] ;Point to filename and print it.
- CALL WRITE_STRING
- MOV AL,RT_BAR_CHAR ;Finish frame with right bar char
- CALL WRITE_SCREEN
- POP DI ;Restore display pointer.
- MOV AX,COLS
- SHL AX,1
- MOV DL,WINDOW_SIZE
- INC DL ;Multiply line length by window
- MUL DL ; size plus one and add to
- ADD DI,AX ; current position to get to
- ADD BP,2 ; next position to display line.
- JMP SHORT NEXT_LINE
- SETUP_END: RET
-
- DISPLAY_SETUP ENDP
-
- ;-----------------------------------;
- ; INPUT ;
- ; None ;
- ; ;
- ; OUTPUT ;
- ; None ;
- ; ;
- ; All registers destroyed. ;
- ;-----------------------------------;
-
- DISPLAY_MENU PROC NEAR
-
- MOV SI,OFFSET MENU ;Point to menu.
- MOV DI,STATUS_LINE ;Point to status line.
- MOV BH,NORMAL_ATTRIB ;Use normal attribute
- CALL WRITE_STRING ; and display menu.
- RET
-
- DISPLAY_MENU ENDP
-
- ;-----------------------------------;
- ; INPUT ;
- ; BP = file index ;
- ; ;
- ; OUTPUT ;
- ; None ;
- ; ;
- ; All registers destroyed. ;
- ;-----------------------------------;
-
- PROMPT_USER PROC NEAR
-
- CMP SYNTAX_FLAG,1 ;If first time through, display
- JZ NEXT_PROMPT ; syntax message.
- MOV SYNTAX_FLAG,1
- MOV DX,OFFSET SYNTAX_MSG
- CALL PRINT_STRING
-
- NEXT_PROMPT: MOV DX,PROMPT[BP] ;Retrieve appropriate prompt
- CALL PRINT_STRING ; and display.
- MOV DI,FILENAME[BP] ;Retrieve address of filename
- MOV DX,DI ; storage and save.
- SUB DX,2 ;Put in first byte of filename
- MOV BX,DX ; buffer, the buffer length (80).
- MOV BYTE PTR [BX],SPEC_LENGTH
- MOV AH,0AH
- INT 21H ;Buffered Keyboard Input.
- PUSH DI ;Save filename pointer.
- MOV AL,CR ;Carriage return points
- ASCIIZ: SCASB ; to last byte of input.
- JNZ ASCIIZ
- MOV BYTE PTR [DI-1],0 ;Replace it with zero (ASCIIZ).
- POP DI ;Retrieve filename pointer.
- MOV DX,DI
- CALL OPEN_FILE ;Attempt to open the file.
- JNC PROMPT_END ;If successful, done here.
- MOV DX,OFFSET NOT_FOUND_MSG ;Else, display "Not found"
- CALL PRINT_STRING ; message
- JMP SHORT NEXT_PROMPT ; and prompt user again.
- PROMPT_END: RET
-
- PROMPT_USER ENDP
-
- ;-------------------------------------;
- ; INPUT ;
- ; SI = points to string to display. ;
- ; Entry point is WRITE_STRING. ;
- ; ;
- ; OUTPUT ;
- ; None ;
- ; ;
- ; All registers destroyed. ;
- ;-------------------------------------;
-
- WRITE_IT: CALL WRITE_SCREEN ;Write a character.
- WRITE_STRING: LODSB ;Retrieve a character.
- CMP AL,SPACE ;Keep writing until a carriage
- JAE WRITE_IT ; return or space encountered.
- RET
-
- ;-------------------;
- ; BIOS Keyboard I/O ;
- ;-------------------;
-
- READ_KEY: MOV AH,0 ;Wait for next keyboard
- INT 16H ; input.
- RET
-
- CK_KEY: MOV AH,1 ;See if character ready.
- INT 16H
- RET
-
- CLEAR_IT: CALL READ_KEY ;If characters are ready
- CLEAR_KEY: CALL CK_KEY ; read them to clear keyboard
- JNZ CLEAR_IT ; buffer.
- RET
-
- ;---------------------------;
- ; Screen clearing routines. ;
- ;---------------------------;
-
- CLS: XOR CX,CX ;Top left corner.
- MOV DX,COLS ;Right corner
- DEC DL
- MOV DH,ROWS ;Bottom row.
- JMP SHORT CLEAR_WINDOW ;Clear the screen.
-
- CLS_WINDOWS: MOV CX,0200H ;Row 3; column zero.
- MOV DX,COLS ;Right corner.
- DEC DL
- MOV DH,WINDOW_SIZE ;Bottom of window one.
- INC DH
- CALL CLEAR_WINDOW ;Clear the window.
- ADD CH,WINDOW_SIZE ;Increment a window size
- INC CH ; and a delimiting line.
- ADD DH,WINDOW_SIZE
- INC DH
- JMP SHORT CLEAR_WINDOW ;Clear second window.
-
- CLS_MENU: MOV CH,ROWS ;Bottom row.
- XOR CL,CL ;Column zero.
- MOV DH,CH
- MOV DL,2CH ;To column 44.
-
- CLEAR_WINDOW: PUSH BX ;Preserve BX.
- MOV BH,NORMAL_ATTRIB ;Normal attribute.
- MOV AX,600H ;Scroll active page.
- INT 10H
- POP BX ;Restore BX.
- RET
-
- ;-------------------;
- ; DOS print string. ;
- ;-------------------;
-
- PRINT_STRING PROC NEAR
-
- MOV AH,9
- INT 21H
- RET
-
- PRINT_STRING ENDP
-
- ;----------------------------------------------------------;
- ; Buffered keyboard input and file buffers at end of code. ;
- ;----------------------------------------------------------;
-
- EVEN
-
- FILESPEC EQU $
- FILE1_BUFFER1 EQU FILESPEC + 2 * (SPEC_LENGTH + 2)
- FILE1_BUFFER2 EQU FILE1_BUFFER1 + TEN_K
- FILE2_BUFFER1 EQU FILE1_BUFFER2 + TEN_K
- FILE2_BUFFER2 EQU FILE2_BUFFER1 + TEN_K
-
- _TEXT ENDS
- END START